<?php

namespace App\Http\Rest\Admin\Resource;

use App\Http\Entities\DddEventEntity;
use App\Http\Rest\Admin\DbResource;
use Framework\Foundation\Database\FDB;
use think\facade\Db;
use Framework\Foundation\Response\ResponseGen;

/**
 * 自动ER图
 * https://gojs.net/latest/download.html
 * https://gojs.net/latest/samples/entityRelationship.html
 * https://github.com/NorthwoodsSoftware/GoJS
 * Class DddEr
 * @package App\Http\Rest\Admin\Resource
 */
class DddEr extends DbResource
{

    /**
     * @var array 建立ER关系忽略这些字段
     */
    protected $ignoreField = [
        'deleted_at',
        'created_at',
        'updated_at',
        'is_deleted',
        'status',
        'sys_update_dc'
    ];

    public function getList(array $restParams, $request)
    {
        $search = $request->getIn('search');
        $type = $request->getIn('type', 'event_id'); // 数据流IDs, 事务id，事件ID

        $scope = $request->getIn('scope', 'columns'); // columns 和 update_columns

        switch ($type) {
            case "stream_ids":
                $streamList = $this->getStreamList(explode(',', $search));
                break;
            case "event_id":
                $streamList = $this->getEventStreamList($search);
                break;
            case "transaction_id":
                $streamList = $this->getStreamListByTransactionId($search);
                break;
            default:
                throw new \Exception("不支持类型");
                break;
        }

        $erList = $this->processStreamListToErData($streamList, $scope);
        return $erList;
    }

    public function getStreamList($streamIds)
    {
        $list = Db::table('ddd_event_stream')
            ->whereIn('ddd_event_stream_id', $streamIds)
            ->group('db_name')
            ->group('table_name')
            ->select()->toArray();

        return $list;
    }

    public function getEventStreamList($eventId)
    {
        $eventInfo = DddEventEntity::getByPk($eventId);
        if (empty($eventInfo)) {
            return [];
        }

        $ids = $eventInfo->streamIds();
        $streamList = Db::table('ddd_event_stream')
            ->whereIn('ddd_event_stream_id', $ids)
            ->group('db_name')
            ->group('table_name')
            ->select()->toArray();

        return $streamList;
    }

    public function getStreamListByTransactionId($transactionId)
    {
        $streamList = Db::table('ddd_event_stream')
            ->where('transaction_tag', $transactionId)
            ->group('db_name')
            ->group('table_name')
            ->select()->toArray();

        return $streamList;
    }

    public function processStreamListToErData($streamList, $scope, $filter = true)
    {
        $nodeData = [];
        $linkData = [];
        $linkSource = [];
        foreach ($streamList as $info) {
            $columns = explode(',', $info[$scope]);

            $entity = [];
            $entity['key'] = $info['db_name'] . '.' . $info['table_name'];
            $items = [];
            foreach ($columns as $columnName) {
                $items[] = [
                    'name' => $columnName,
                    'iskey' => $info['db_name'] . '_id' == $columnName,
//                    'figure' => ''
//                    'color' => ''
                ];
            }
            $entity['items'] = $items;
            $nodeData[] = $entity;

            if ($filter) {
                $filterColumns = array_diff(
                    $columns,
                    $this->ignoreField
                );
                $linkSource[] = ['key' => $entity['key'], 'columns' => $filterColumns];
            } else {
                $linkSource[] = ['key' => $entity['key'], 'columns' => $columns];
            }
        }

        $count = count($linkSource);
        if ($count > 1) {
            for ($i = 0; $i < $count; $i++) {
                for ($j = $i + 1; $j < $count; $j++) {
                    $ret = array_intersect($linkSource[$i]['columns'], $linkSource[$j]['columns']);
                    if (!empty($ret)) {
                        $data = [
                            'from' => $linkSource[$i]['key'],
                            'to' => $linkSource[$j]['key'],
                            'text' => implode(',', $ret),
//                            'toText' => ''
                        ];
                        $linkData[] = $data;
                    }
                }
            }
        }

        return ['nodeData' => $nodeData, 'linkData' => $linkData];
    }
}
